package com.linx.commonlib.recyclerview

import android.content.Context
import android.graphics.Canvas
import android.graphics.Rect
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.util.Log
import android.view.View
import android.widget.LinearLayout
import com.linx.commonlib.dp2px

private const val TAG = "Divider"

/**
 * @param dividerWidth item offset width, -1 mean use drawable intrinsicWidth or intrinsicHeight
 */
class Divider(private val context: Context, private val orientation: Int,
              private val dividerWidth: Int = -1,
              private val dividerPadding: Int = 0,
              private val includeEnd: Boolean = true) : androidx.recyclerview.widget.RecyclerView.ItemDecoration() {

    companion object {
        private val ATTRS = intArrayOf(android.R.attr.listDivider)
        @Suppress("unused")
        const val HORIZONTAL = LinearLayout.HORIZONTAL
        const val VERTICAL = LinearLayout.VERTICAL
    }

    private val mBounds = Rect()
    private var mDivider: Drawable?
    private var itemOffset = 0

    init {
        val a = context.obtainStyledAttributes(ATTRS)
        val divider = a.getDrawable(0)
        if (divider == null) {
            Log.w(TAG, "@android:attr/listDivider was not set in the theme used for this " + "DividerItemDecoration. Please set that attribute all call setDrawable()")
        } else {
            setDrawable(divider)
        }
        mDivider = divider
        a.recycle()
    }

    @Suppress("MemberVisibilityCanBePrivate")
    fun setDrawable(drawable: Drawable) {
        mDivider = drawable
        itemOffset = if (dividerWidth == -1) {
            if (orientation == VERTICAL) drawable.intrinsicHeight else drawable.intrinsicWidth
        } else {
            dividerWidth
        }
    }

    fun setColor(color: Int, dp: Float = 1f) {
        setDrawable(object : ColorDrawable(color) {

            override fun getIntrinsicWidth(): Int {
                return context.dp2px(dp)
            }

            override fun getIntrinsicHeight(): Int {
                return context.dp2px(dp)
            }

        })
    }

    override fun onDraw(c: Canvas, parent: androidx.recyclerview.widget.RecyclerView, state: androidx.recyclerview.widget.RecyclerView.State) {
        if (parent.layoutManager == null || mDivider == null) {
            return
        }
        if (orientation == VERTICAL) {
            drawVertical(c, parent)
        } else {
            drawHorizontal(c, parent)
        }
    }

    private fun drawVertical(canvas: Canvas, parent: androidx.recyclerview.widget.RecyclerView) {
        canvas.save()
        val left: Int
        val right: Int

        if (parent.clipToPadding) {
            left = parent.paddingLeft + dividerPadding
            right = parent.width - parent.paddingRight - dividerPadding
            canvas.clipRect(left, parent.paddingTop, right,
                    parent.height - parent.paddingBottom)
        } else {
            left = dividerPadding
            right = parent.width - dividerPadding
        }

        val drawCount = fetchDrawCount(parent)
        mDivider?.apply {
            for (i in 0 until drawCount) {
                val child = parent.getChildAt(i)
                parent.getDecoratedBoundsWithMargins(child, mBounds)
                val bottom = mBounds.bottom + Math.round(child.translationY)
                val top = bottom - intrinsicHeight
                setBounds(left, top, right, bottom)
                draw(canvas)
            }
        }
        canvas.restore()
    }

    private fun drawHorizontal(canvas: Canvas, parent: androidx.recyclerview.widget.RecyclerView) {
        canvas.save()
        val top: Int
        val bottom: Int

        if (parent.clipToPadding) {
            top = parent.paddingTop
            bottom = parent.height - parent.paddingBottom
            canvas.clipRect(parent.paddingLeft, top,
                    parent.width - parent.paddingRight, bottom)
        } else {
            top = 0
            bottom = parent.height
        }

        val drawCount = fetchDrawCount(parent)
        mDivider?.apply {
            for (i in 0 until drawCount) {
                val child = parent.getChildAt(i)
                parent.layoutManager?.getDecoratedBoundsWithMargins(child, mBounds)
                val right = mBounds.right + Math.round(child.translationX)
                val left = right - intrinsicWidth
                setBounds(left, top, right, bottom)
                draw(canvas)
            }
        }
        canvas.restore()
    }

    private fun fetchDrawCount(parent: androidx.recyclerview.widget.RecyclerView): Int {
        val childCount = parent.childCount
        return if (includeEnd) {
            childCount
        } else {
            val pos = parent.getChildAdapterPosition(parent.getChildAt(childCount - 1))
            if (pos == parent.adapter!!.itemCount - 1) {
                childCount - 1
            } else {
                childCount
            }
        }
    }

    override fun getItemOffsets(outRect: Rect, view: View, parent: androidx.recyclerview.widget.RecyclerView,
                                state: androidx.recyclerview.widget.RecyclerView.State) {
        if (mDivider == null) {
            outRect.set(0, 0, 0, 0)
            return
        }
        mDivider?.apply {
            val adapter = parent.adapter
            if (adapter != null) {
                val count = adapter.itemCount
                val index = parent.getChildAdapterPosition(view)
                if (includeEnd || index < count - 1) {
                    if (orientation == VERTICAL) {
                        outRect.set(0, 0, 0, itemOffset)
                    } else {
                        outRect.set(0, 0, itemOffset, 0)
                    }
                } else {
                    outRect.set(0, 0, 0, 0)
                }
            }
        }
    }

}